#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1

command -v getarg >/dev/null || . /usr/lib/dracut-lib.sh

set -e

UNIT_DIR="${1:-/tmp}"

add_requires() {
    local name="$1"; shift
    local target="$1"; shift
    local requires_dir="${UNIT_DIR}/${target}.requires"
    mkdir -p "${requires_dir}"
    ln -sf "../${name}" "${requires_dir}/${name}"
}

if ! is-live-image; then
    exit 0
fi

# Create stamp file that everything else should use to detect a live boot
> /run/ostree-live

add_requires sysroot.mount     initrd-root-fs.target
add_requires sysroot-etc.mount initrd-root-fs.target
add_requires sysroot-var.mount initrd-root-fs.target

add_requires coreos-liveiso-network-kargs.service              initrd.target
add_requires coreos-liveiso-reconfigure-nm-wait-online.service initrd.target

mkdir -p "${UNIT_DIR}/ostree-prepare-root.service.d"
cat > "${UNIT_DIR}/ostree-prepare-root.service.d/10-live.conf" <<EOF
# With live PXE there's no ostree= argument on the kernel command line, so
# we need to find the tree path and pass it to ostree-prepare-root.  But
# ostree-prepare-root only knows how to read the path from
# /proc/cmdline, so we need to synthesize the proper karg and bind-mount
# it over /proc/cmdline.
# https://github.com/ostreedev/ostree/issues/1920

[Unit]
# The base unit conditions on the ostree karg, which won't exist until
# ExecStartPre runs
ConditionKernelCommandLine=

[Service]
ExecStartPre=/usr/sbin/ostree-cmdline start
ExecStartPost=/usr/sbin/ostree-cmdline stop
EOF

# In this case, the rootfs is directly in the initramfs
if [ -f /root.squashfs ]; then
    cat >"${UNIT_DIR}/sysroot.mount" <<EOF
# Automatically generated by live-generator

[Unit]
DefaultDependencies=false
Before=initrd-root-fs.target

[Mount]
What=/root.squashfs
Where=/sysroot
Type=squashfs
EOF
else
    isoroot=$(getarg coreos.liveiso=)
    if [ -z "${isoroot}" ]; then
        echo "Missing required coreos.liveiso kernel argument" 1>&2
        exit 1
    fi

    # And in this case, it's on the ISO
    mkdir -p /run/media/iso
    isosrc=dev/disk/by-label/${isoroot}
    isosrc_escaped=$(systemd-escape -p --suffix=device "${isosrc}")
    cat >"${UNIT_DIR}/run-media-iso.mount" <<EOF
# Automatically generated by live-generator

[Unit]
DefaultDependencies=false
Before=initrd-root-fs.target
After=${isosrc_escaped}
Requires=${isosrc_escaped}

[Mount]
What=/${isosrc}
Where=/run/media/iso
Type=iso9660
EOF

    cat >"${UNIT_DIR}/sysroot.mount" <<EOF
# Automatically generated by live-generator

[Unit]
DefaultDependencies=false
Before=initrd-root-fs.target
Requires=run-media-iso.mount

[Mount]
What=/run/media/iso/root.squashfs
Where=/sysroot
Type=squashfs
EOF
fi

common_etcvar_unit() {
    cat << EOF
# Automatically generated by live-generator
[Unit]
DefaultDependencies=false

# Make sure /sysroot is mounted first, since we're mounting under there
Requires=initrd-root-fs.target
After=initrd-root-fs.target

# Make sure our tmpfs is available
RequiresMountsFor=/writable

# Need to do this before Ignition mounts any other filesystems (potentially
# shadowing our own mount).
Before=ignition-mount.service
EOF
}

supports_squashfs_overlayfs=1
case "$(uname -r)" in
    4.18.*) supports_squashfs_overlayfs=0
esac

if [ "${supports_squashfs_overlayfs}" = 1 ]; then
    common_etcvar_unit > "${UNIT_DIR}/sysroot-etc.mount"
    cat >>"${UNIT_DIR}/sysroot-etc.mount" <<EOF
[Mount]
What=overlay
Where=/sysroot/etc
Type=overlay
Options=lowerdir=/sysroot/etc,upperdir=/writable/etc/upper,workdir=/writable/etc/work,redirect_dir=on,index=on,xino=on
EOF
else
    # RHEL8 can't do overlayfs on squashfs, so we just copy
    # /etc fully into RAM.  It's not a large amount of data.
    common_etcvar_unit > "${UNIT_DIR}/sysroot-etc-copy.service"
    cat >>"${UNIT_DIR}/sysroot-etc-copy.service" <<EOF
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/cp -a /sysroot/etc /writable/etc-copy
EOF

    common_etcvar_unit > "${UNIT_DIR}/sysroot-etc.mount"
cat >>"${UNIT_DIR}/sysroot-etc.mount" <<EOF
After=sysroot-etc-copy.service
Requires=sysroot-etc-copy.service
[Mount]
What=/writable/etc-copy
Where=/sysroot/etc
Type=none
Options=bind
EOF
fi

common_etcvar_unit >"${UNIT_DIR}/sysroot-var.mount"
cat >>"${UNIT_DIR}/sysroot-var.mount" <<EOF
[Mount]
What=/writable/var
Where=/sysroot/var
Type=none
Options=bind
EOF
